package com.littcore.saas.rest.assistant;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.jsondoc.core.annotation.Api;
import org.jsondoc.core.annotation.ApiMethod;
import org.jsondoc.core.annotation.ApiQueryParam;
import org.jsondoc.core.annotation.ApiResponseObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.littcore.common.BeanManager;
import com.littcore.common.Utility;
import com.littcore.dao.page.IPageList;
import com.littcore.dao.ql.PageParam;
import com.littcore.exception.BusiCodeException;
import com.littcore.exception.NotLoginException;
import com.littcore.io.fileupload.HttpFileUpload;
import com.littcore.io.fileupload.UploadFile;
import com.littcore.module.annotation.Func;
import com.littcore.saap.assistant.po.Attachment;
import com.littcore.saap.assistant.service.IAttachmentService;
import com.littcore.saap.assistant.vo.AttachmentVo;
import com.littcore.saap.core.web.util.LoginUtils;
import com.littcore.web.mvc.action.BaseController;
import com.littcore.web.util.WebUtils;

@Api(name = "附件接口", description = "附件相关的功能")
@Controller
public class AttachmentServiceController extends BaseController{
    
    @Resource
    private IAttachmentService attachmentService;
    
    @ApiMethod(description = "根据模块和记录ID获取附件")
    @ApiResponseObject
    @RequestMapping
    @ResponseBody
    public List<AttachmentVo> getAttachments(@ApiQueryParam(name = "moduleCode") @RequestParam String moduleCode,@ApiQueryParam(name = "recordId") @RequestParam Integer recordId,
            @ApiQueryParam(name="pageIndex", description="page index") @RequestParam(required = false, defaultValue = "1") int pageIndex,
            @ApiQueryParam(name="pageSize", description="page size" ) @RequestParam(required = false, defaultValue = "15") int pageSize) throws NotLoginException
    { 
      PageParam pageParam = new PageParam(pageIndex, pageSize);
      pageParam.addCond("tenantId", LoginUtils.getTenantId());  
      pageParam.addCond("isDeleted", false);  
      pageParam.addCond("moduleCode", moduleCode);
      pageParam.addCond("recordId", recordId);
      
      pageParam.addSort("obj.updateDatetime", "desc");
      //Get page result
      IPageList pageList = attachmentService.listPage(pageParam);   
      
       
      return pageList.getRsList();
    
    } 
    
    @ApiMethod(description = "获取附件")
    @ApiResponseObject
    @RequestMapping
    @ResponseBody
    public Attachment getAttachmentById(@ApiQueryParam(name = "id") @RequestParam Integer id) 
    { 
      Attachment attachment = attachmentService.load(id);   
        return attachment;
      }
    
    
    @ApiMethod(description = "上传附件,需要加参数moduleCode和recordId,moduleCode可为task/shareFile...")
    @ApiResponseObject
    @RequestMapping 
    public ModelAndView upload(HttpServletRequest request, HttpServletResponse response) throws Exception
    { 
      String homePath = super.getHomePath();
      int tenantId = LoginUtils.getTenantId();
      
      String characterEncoding = request.getCharacterEncoding();  //编码      
      DiskFileItemFactory factory = new DiskFileItemFactory();
      factory.setSizeThreshold(4096); //内存使用4K  
      String uploadPath = tenantId + File.separator + "tmp";  //相对目录, 租户下临时目录     
      String finalPath = homePath + File.separator + uploadPath;
      HttpFileUpload fileUpload = new HttpFileUpload(homePath, uploadPath, factory);
      fileUpload.setAllowField(true); //允许表单字段
      fileUpload.setHeaderEncoding(characterEncoding); //设置头编码
      fileUpload.setSizeMax(100L * 1024 * 1024 * 1024); //设置最大上传尺寸10G
      fileUpload.setFileSizeMax(1024L * 1024 * 1024); //设置单个文件上传尺寸1G    
      try
      {
        fileUpload.parseRequest(request);
        fileUpload.upload();  //上传文件并保存
        
        //上传成功的文件记录到数据库
        String moduleCode = fileUpload.getParameter("moduleCode");
        int recordId = Utility.parseInt(fileUpload.getParameter("recordId"));
        List<UploadFile> fileList = fileUpload.getSucceedFiles();
        List<AttachmentVo> attachmentList = new ArrayList<>();
        for (UploadFile uploadFile : fileList) {
          File srcFile = new File(uploadFile.getFilePath(), uploadFile.getFileName());
          try {
            AttachmentVo attachment = attachmentService.save(srcFile, moduleCode, tenantId, recordId);
            attachmentList.add(attachment);
            
            uploadFile.setUid(attachment.getUid());
            uploadFile.setFileName(attachment.getFileName()); //文件名被重命名过
          } catch (BusiCodeException e) {
            uploadFile.setErrorCode(e.getErrorCode());
            uploadFile.setErrorMessage(BeanManager.getMessage(e.getErrorCode(), LoginUtils.getLocale(request)));
          }
        }
        return new ModelAndView("jsonView").addObject("error", false).addObject("fileList", fileList).addObject("attachmentList", attachmentList);      
      }
      catch (BusiCodeException e)
      {
        logger.error("File upload failed.", e);
        return new ModelAndView("jsonView").addObject("error", true).addObject("errorMessage", BeanManager.getMessage(e.getErrorCode(), LoginUtils.getLocale(request)));
      }
      catch (Exception e)
      {
        logger.error("File upload failed.", e);
        return new ModelAndView("jsonView").addObject("error", true).addObject("errorMessage", BeanManager.getMessage("attachement.error.uploadFileFailed", LoginUtils.getLocale(request)));
      }
      finally
      {
        fileUpload.dispose();
      }     
      
    } 
    
    @ApiMethod(description = "下载附件")
    @ApiResponseObject
    @RequestMapping 
    public void download(@ApiQueryParam(name = "id") @RequestParam(required=false) Integer id,@ApiQueryParam(name = "uid") @RequestParam(required=false) String uid
        , HttpServletRequest request, HttpServletResponse response) throws Exception
    { 
      String homePath = super.getHomePath();
      
      Attachment attachment = attachmentService.download(id, uid);
      File dir = new File(homePath, attachment.getFilePath());
      File file = new File(dir, attachment.getFileName());
      
      super.download(response, attachment.getDisplayName(), file);
    } 
    
    
    @ApiMethod(description = "打开附件")
    @ApiResponseObject
    @RequestMapping 
    public void open(@ApiQueryParam(name = "id") @RequestParam(required=false) Integer id,@ApiQueryParam(name = "id") @RequestParam(required=false) String uid
        , HttpServletRequest request, HttpServletResponse response) throws Exception
    { 
      String homePath = super.getHomePath();
      
      Attachment attachment = attachmentService.open(id, uid);
     
      File dir = new File(homePath, attachment.getFilePath());
      File file = new File(dir, attachment.getFileName());
      String fileName = attachment.getDisplayName();
      try
      {
        fileName = URLEncoder.encode(fileName, "utf-8");
      }
      catch (UnsupportedEncodingException e)
      {
        logger.error("Encode FileName Error:", e);
        throw new RuntimeException(e);
      }
      response.reset();
      String content = "inline; filename=" + fileName;
      response.addHeader("Content-Disposition", content);
      response.setCharacterEncoding("utf-8");
      InputStream stream = null;
      try
      {
        stream = new FileInputStream(file);
        responseBinaryStream(response, WebUtils.getContentType(FilenameUtils.getExtension(fileName)), stream);     
      }
      catch (FileNotFoundException e)
      {
        logger.error("FileNotFoundException for " + file.getAbsolutePath());
        throw new RuntimeException(e);
      }   
      finally
      {
        IOUtils.closeQuietly(stream);
      }
    } 
    
 
    //@Func(funcCode="delete",moduleCode="assistant.attachment")
    @ApiMethod(description = "删除附件")
    @ApiResponseObject
    @RequestMapping
    @ResponseBody
    public void delete( @ApiQueryParam(name="id")  @RequestParam(required=true) Integer id) throws Exception
    {
      attachmentService.delete(id);
    }

    
    //@Func(funcCode="delete",moduleCode="assistant.attachment")
    @ApiMethod(description = "按名称删除")
    @ApiResponseObject
    @RequestMapping
    @ResponseBody
    public void deleteByName(@ApiQueryParam(name="moduleCode", description="模块名")@RequestParam(required=true) String moduleCode, @RequestParam(required=true) Integer recordId, @RequestParam(required=true) String fileName) throws Exception
    {
      int tenantId = LoginUtils.getTenantId();
      
      attachmentService.deleteByName(tenantId, moduleCode, recordId, fileName);   
      
    }
    
   // @Func(funcCode="delete",moduleCode="assistant.attachment")
    @ApiMethod(description = "按名称删除")
    @ApiResponseObject
    @RequestMapping
    @ResponseBody
    public void deleteByUid(@ApiQueryParam(name="uid") @RequestParam String uid) throws Exception
    {
      attachmentService.deleteByUid(uid);   
    }
    
}
